package cn.jinjimi.app.webview;

import android.content.Context;
import android.text.TextUtils;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;

import org.greenrobot.eventbus.EventBus;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

import bolts.Task;
import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.webview.bean.SetTitleAction;
import cn.jinjimi.app.webview.bean.ShareAction;
import cn.jinjimi.app.webview.bean.UploadPhotoAction;
import cn.jinjimi.app.webview.bean.WXPayOrder;
import cn.jinjimi.app.webview.event.ReqSetTitleEvent;
import cn.jinjimi.app.webview.event.ReqUploadPhotoEvent;
import cn.jinjimi.base.util.GsonUtils;
import cn.jinjimi.framework.pay.AbstractPayTask;
import cn.jinjimi.framework.pay.IPayResultCallback;
import cn.jinjimi.framework.pay.IPayType;
import cn.jinjimi.framework.pay.PayManager;
import cn.jinjimi.framework.pay.PayResult;

/**
 *
 * @author zhenhua
 * @date 16/1/23
 */
public class WebViewJavascriptBridge extends AbstractJavascriptBridge {
    private static final String TAG = "WebViewJavascriptBridge";
    public static final String JS_BRIDGE_NAME = "WebViewJavascriptBridge";
    private static Map<String, AbstractNativeHandler> mHandlers;

    private boolean enableJs = true;

    /**
     * 本地方法只注册一次
     */
    static {
        mHandlers = new HashMap<>();
        registerDefaultNativeHandlers();
    }

    /**
     * 当前的WebView对象
     */
    private final WebView mWebView;

    /**
     * 当前WebView绑定的回调函数
     */
    private AbstractJSHandler mJSHandler;

    public WebViewJavascriptBridge(WebView webView) {
        mWebView = webView;
        mWebView.addJavascriptInterface(new DefaultJavaScriptInterface(), JS_BRIDGE_NAME);
    }

    public static void onRefreshWebView(WebView webView){
        if(webView != null){
            webView.loadUrl("javascript:onRefresh()");
        }
    }

    public void enableJavascriptInterface(boolean enableJs) {
        this.enableJs = enableJs;
    }

    /**
     * 调用已经注册的Native回调方法
     *
     * @param data
     */
    @Override
    public void callNativeHandler(String data) {
        if (!enableJs) {
            return;
        }

        BaseAction action = GsonUtils.fromJson(data, BaseAction.class);
        if (action != null) {
            for (AbstractNativeHandler handler : mHandlers.values()) {
                if (TextUtils.equals(handler.getName(), action.action)) {
                    //执行Native方法
                    BaseAction result = handler.call(this, data);
                    //执行回调
                    if (result != null) {
                        callJSHandler(action.callbackFunction, result);
                    }
                }
            }
        }
    }

    /**
     * 调用JS方法
     *
     * @param callback
     * @param data
     */
    @Override
    public void callJSHandler(String callback, Object data) {
        if (mJSHandler == null) {
            mJSHandler = createDefaultJSHandlers();
        }
        mJSHandler.call(callback, data);
    }

    @Override
    public Context getContext() {
        if (mWebView != null) {
            return mWebView.getContext();
        }
        return null;
    }


    /**
     * JS回调函数
     */
    private AbstractJSHandler createDefaultJSHandlers() {
        //default js handler;
        return new AbstractJSHandler() {
            @Override
            public void call(final String callback, final Object data) {
                Task.call(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        if (mWebView != null) {
                            String param = data == null ? "" : GsonUtils.toJson(data);
                            mWebView.loadUrl(String.format("javascript:%s('%s')", callback, param));
                        }
                        return null;
                    }
                }, Task.UI_THREAD_EXECUTOR);

            }
        };
    }


    /**
     * 注册原生的回调方法
     *
     * @param handler
     */
    public static void registerNativeHandler(AbstractNativeHandler handler) {
        mHandlers.put(handler.getName(), handler);
    }

    /**
     * 注册默认的Native回调函数
     */
    private static void registerDefaultNativeHandlers() {
        registerNativeHandler(new AbstractNativeHandler() {
            @Override
            public BaseAction call(AbstractJavascriptBridge bridge, String data) {
                BaseAction action = GsonUtils.fromJson(data, BaseAction.class);
                AccountManager.getInstance().logout();
                return action;
            }

            @Override
            public String getName() {
                return Actions.LOG_OUT;
            }
        });

        registerNativeHandler(new AbstractNativeHandler() {
            @Override
            public BaseAction call(AbstractJavascriptBridge bridge, String data) {
                SetTitleAction action = GsonUtils.fromJson(data, SetTitleAction.class);
                if (action != null) {
                    EventBus.getDefault().post(new ReqSetTitleEvent(action.title));
                }
                return action;
            }

            @Override
            public String getName() {
                return Actions.SET_TITLE;
            }
        });

        registerNativeHandler(new AbstractNativeHandler() {
            @Override
            public BaseAction call(AbstractJavascriptBridge bridge, String data) {
                UploadPhotoAction action = GsonUtils.fromJson(data, UploadPhotoAction.class);
                if (action != null) {
                    EventBus.getDefault().post(new ReqUploadPhotoEvent(action));
                }
                return null;
            }

            @Override
            public String getName() {
                return Actions.UPLOAD_PHOTO;
            }
        });

        registerNativeHandler(new AbstractNativeHandler() {
            @Override
            public BaseAction call(AbstractJavascriptBridge bridge, String data) {
                ShareAction action = GsonUtils.fromJson(data, ShareAction.class);
                if (action != null) {
                    EventBus.getDefault().post(action);
                }
                return null;
            }

            @Override
            public String getName() {
                return Actions.SHARE;
            }
        });

        registerNativeHandler(new AbstractNativeHandler() {
            @Override
            public BaseAction call(AbstractJavascriptBridge bridge, String data) {
                WXPayOrder action = GsonUtils.fromJson(data, WXPayOrder.class);
                Context context = bridge.getContext();
                if (context != null) {
                    //create a new pay task
                    AbstractPayTask task = PayManager.newPayTask(context, IPayType.WECHAT);
                    //register callback & commit
                    if (task != null) {
                        task.setPayResultCallback(new IPayResultCallback() {
                            @Override
                            public void onResult(PayResult result) {

                            }
                        });

                        task.pay(action.toPayOrder());
                    }
                }
                return action;
            }

            @Override
            public String getName() {
                return Actions.WXPAY;
            }
        });


    }

    /**
     * 默认注册的Action
     */
    public interface Actions {
        String UPLOAD_PHOTO = "uploadPhoto";
        String LOG_OUT = "logout";
        String SET_TITLE = "setTitle";
        String SHARE = "share";
        String WXPAY = "WXPay";
    }

    /**
     * 默认对外提供的JS接口
     *
     * @see AbstractJavascriptBridge registerNativeHandler
     */
    public class DefaultJavaScriptInterface {
        private static final String METHOD = "call";
        @JavascriptInterface
        public void callHandler(String method, String data) {
            if (TextUtils.equals(METHOD, method)) {
                callNativeHandler(data);
            }
        }
    }

}
